#!/bin/sh
MYDIR=$(dirname "$0")
sequence=$1
result=$2

cd "$MYDIR"


await()
{
  while [ ! -e "llt_$1.tmp" ]; do
    :
  done
}


run()
{
  ./loglinear ./loglinear_test "$1"
  touch "llt_e$1.tmp"
}


check_sequence()
{
  while read header magic val; do
    echo "check: $header $magic $val"
    if [ "$magic" = "START" -o "$magic" = "STOP" ]; then
      if [ "$val" = "$1" ]; then
        shift
      else
        echo "FAILED: expected '$1', got '$val'" >&2
        return 1
      fi
    fi
  done

  if [ $# != 0 ]; then
    echo "FAILED: remaining sequence not found: '$*'" >&2
    return 2
  fi
}


main()
{
  # This requires a bit of explanation.
  #
  # First, remember the goal: we want to print logs that pass first, so that
  # failures end up near the end.  And "inner" failures come after "outer"
  # failures: if a parent and his child both fail, we mostly care about the
  # child, because the parent probably only failed because the child failed,
  # and the child will have the most specific error message.  Other than this
  # restriction, we want to generally keep things in chronological order.
  #
  # So our test works like this:
  #  1 runs 2a/2b.  2a runs 3a/3b.  2b runs 3c.
  #  We print logs from steps that succeed first: that's 2b, 3a, 3b.
  #  2b is dragged downwards, however, because its child, 3c, fails, so the
  #   other two are printed before it.
  #  So 3a and 3b first.  3b is set to wait for 3a, so 3a prints before 3b.
  #
  #  1, 2a, and 3c all fail.  3c is owned by 2b, though, which didn't fail,
  #   so 2b is not as important as 2a, which failed.  Thus we print 2b
  #   before 2a.  We print parents before their failing children, so 2b
  #   comes before 3c.
  #  Now 1 and 2a are left.  They both failed, and 1 is 2a's parent, so
  #   it comes first, followed by 2a.
  #
  # Obviously, right?
  EXPECT="s3a e3a s3b e3b s2b e2b s3c e3c s1 e1 s2a e2a"
  echo
  echo
  rm -f llt_*.tmp
  (
    echo -n "MAIN "
    run 1 2>&1
  ) | check_sequence $EXPECT
}


echo "START s$sequence"
touch "llt_s$sequence.tmp"
rv=101
case "$sequence" in
  1) run 2a & (await s2a; run 2b) & wait; rv=1 ;;
  2a) run 3a & (await s3a; run 3b) & wait; rv=2 ;;
  2b) run 3c; rv=0 ;;
  3a) rv=0 ;;
  3b) await e3a; rv=0 ;;
  3c) rv=5 ;;
  "")
    # we were run with no parameters: initial startup.
    # Run main() several times in case the test has race conditions.
    if main && main && main && main && main; then
      echo
      echo "Passed!"
      exit 0
    else
      rv=$?
      echo
      echo "Failed: code $rv"
      exit $rv
    fi
    ;;
  *)
    echo "Unexpected sequence number: '$sequence'" >&2
    exit 98
    ;;
esac
echo "STOP  e$sequence"

exit $rv
